package com.cetcs.kmga.dataManager.dao.hbase.impl;

import com.cetc.cloud.kmga.util.DateUtils;
import com.cetcs.kmga.dataManager.dao.hbase.ILogManagerDao;
import com.cetcs.kmga.dataManager.entity.logManager.ProbeLogIndex;
import com.cetcs.kmga.dataManager.entity.logManager.vo.LogTbKvVo;
import com.cetcs.kmga.dataManager.util.HBaseDataGetter;
import com.cetcs.kmga.dataManager.util.HBasePageModel;
import com.cetcs.kmga.dataManager.util.HBasePool;
import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.filter.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * 类注释
 *
 * @author xutao
 * @version V1.0 创建时间：2017-09-07 14:28
 * Copyright 2017 by CETC
 */
@Repository
public class LogManagerDaoImpl implements ILogManagerDao {

    private static Logger LOG = LoggerFactory.getLogger(LogManagerBaseDaoImpl.class);

    private final static String INDEX_NAME = "KMGA:";

    /**
     * 默认一次性最大查询条数
     */
    private final static int MAX_QUERY_LENGTH = 100000;

    private static boolean isExport=true;

    /**
     * 探针补位最大值
     */
    private final static String PROBE_MAX_FLAG = "9999999999";

    /**
     * 探针补位最小值
     */
    private final static String PROBE_MIN_FLAG = "1000000000";

    private final static String PROBE_INDEX_FLAG = "|";

    private final ExecutorService FIXED_ALL_LENGTH_POOL = Executors.newFixedThreadPool(20);

    /**
     * 获取日志的公共方法
     *
     * @param type                类型
     * @param columnArr           参数数组
     * @param startTime           起始时间
     * @param endTime             结束时间
     * @param fuzzyIndexParams    模糊匹配的参数
     * @param accurateIndexParams 精确匹配的参数
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    @Override
    public HBasePageModel findProbeInfoByCondition(String type, List<String> columnArr, Date startTime, Date endTime, List<LogTbKvVo> fuzzyIndexParams, List<LogTbKvVo> accurateIndexParams, boolean isNotExport) throws ExecutionException, InterruptedException {

        String startTimeStr = DateUtils.format(startTime, DateUtils.DATE_FORMAT_10);
        String endTimeStr = DateUtils.format(endTime, DateUtils.DATE_FORMAT_10);
        Integer probeMax = 10000;

        HBasePageModel ret = new HBasePageModel();
        isExport=!isNotExport;
        //如果起始时间与结束时间的月份都相等那么数据未进行分表操作
        if (startTimeStr.equals(endTimeStr)) {//执行单表操作
            ret = queryCommonProbeInfoByCondition(type, columnArr, startTime, endTime, fuzzyIndexParams, accurateIndexParams, MAX_QUERY_LENGTH, isNotExport);
        } else {//日期不等于需要进行分表操作，目前只需跨两张表
            //找出终止时间所在月的第一天
            Date neStartDate = DateUtils.getMonthStartTime(endTime);
            ret = queryCommonProbeInfoByCondition(type, columnArr, neStartDate, endTime, fuzzyIndexParams, accurateIndexParams, MAX_QUERY_LENGTH, isNotExport);
            //如果长度小于10万就需要查询下一个时间段
            if (ret.getDataList() == null) {
                ret.setDataList(Lists.newArrayList());
            }
            if (ret.getDataList().size() < probeMax) {
                Date subEndDate = DateUtils.getMonthEndTime(startTime);
                int pageSize = probeMax - ret.getDataList().size();
                HBasePageModel sonRet = queryCommonProbeInfoByCondition(type, columnArr, startTime, subEndDate, fuzzyIndexParams, accurateIndexParams, pageSize, isNotExport);
                //将之后加载的数据合并到一起
                if (sonRet.getDataList() != null && sonRet.getDataList().size() > 0) {
                    ret.getDataList().addAll(sonRet.getDataList());
                }
            }
        }
        return ret;
    }

    @Override
    public HBasePageModel findLogInfoByCondition(String tbName, String type, List<String> columnArr, Date startTime, Date endTime, Map<String, Object> indexParams, boolean isNotExport) throws ExecutionException, InterruptedException {
        isExport=!isNotExport;
        HBasePageModel ret = new HBasePageModel();
        if (indexParams == null || indexParams.size() == 0) {//没有查询索引表的条件
            ret = queryLogInfoNoOtherCondition(getOtherTbName(tbName), type, columnArr, startTime, endTime, MAX_QUERY_LENGTH);
        } else {
            List<List<String>> dbList = findLogInfoIndexTbData(getOtherTbName(tbName), type, columnArr, startTime, endTime, indexParams, MAX_QUERY_LENGTH, isNotExport);
            ret.setDataList(dbList);
        }
        return ret;
    }

    /**
     * 根据主键ID查询日志的详情
     *
     * @param tbName 表名称
     * @param id     主键ID
     * @return
     */
    @Override
    public Map<String, Object> findLogDetailById(String tbName, String id) {
        Map<String, Object> ret = HBasePool.getInstance().findDataDetailByRowKey(getOtherTbName(tbName), id);
        return ret;
    }


    private String getOtherTbName(String tbName) {
        String newTbName = INDEX_NAME + tbName;
        return newTbName;
    }

    /**
     * 获取日志的公共方法
     *
     * @param type                类型
     * @param columnArr           参数数组
     * @param startTime           起始时间
     * @param endTime             结束时间
     * @param fuzzyIndexParams    模糊匹配的参数
     * @param accurateIndexParams 精确匹配的参数
     * @param pageSize            查询的条数
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    private HBasePageModel queryCommonProbeInfoByCondition(String type, List<String> columnArr, Date startTime, Date endTime, List<LogTbKvVo> fuzzyIndexParams, List<LogTbKvVo> accurateIndexParams, Integer pageSize, boolean isNotExport) throws ExecutionException, InterruptedException {
        HBasePageModel ret = new HBasePageModel();
        if (fuzzyIndexParams == null || fuzzyIndexParams.size() == 0) {//没有查询索引表的条件
            List<List<String>> dbList = queryProbeInfoNoOtherCondition(type, columnArr, startTime, endTime, pageSize);
            ret.setDataList(dbList);
        } else {
            List<List<String>> dbList = findProbeIndexTbData(type, columnArr, startTime, endTime, fuzzyIndexParams, accurateIndexParams, pageSize, isNotExport);
            ret.setDataList(dbList);
        }
        return ret;
    }


    /**
     * 根据索引获取数据
     *
     * @param type                类型
     * @param columnArr           数组
     * @param startTime           起始时间
     * @param endTime             结束时间
     * @param fuzzyIndexParams    模糊匹配的参数
     * @param accurateIndexParams 精确匹配的参数
     * @param pageSize            查询的条数
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    private List<List<String>> findProbeIndexTbData(String type, List<String> columnArr, Date startTime, Date endTime, List<LogTbKvVo> fuzzyIndexParams, List<LogTbKvVo> accurateIndexParams, Integer pageSize, boolean isNotExport) throws ExecutionException, InterruptedException {
        List<String> rowKeys = queryProbeIndexRowKeys(type, startTime, endTime, fuzzyIndexParams, accurateIndexParams, pageSize, isNotExport);
        String timeStr = DateUtils.format(startTime, DateUtils.DATE_FORMAT_10);
        String tbName = getProbeTbName(timeStr, type);
        List<List<String>> ret = HBasePool.getInstance().
                findDataFromDbByRowKeys(tbName, rowKeys, columnArr);
        return ret;
    }


    /**
     * 查询非探针日志的查询的索引表的查询方法
     *
     * @param tbName      主表名
     * @param type        类型
     * @param columnArr   数组
     * @param startTime   起始时间
     * @param endTime     结束时间
     * @param indexParams 参数数组
     * @param pageSize    条数
     * @return
     * @throws ExecutionException
     * @throws InterruptedException
     */
    private List<List<String>> findLogInfoIndexTbData(String tbName, String type, List<String> columnArr, Date startTime, Date endTime, Map<String, Object> indexParams, Integer pageSize, boolean isNotExport) throws ExecutionException, InterruptedException {
        String rowIndexTbName = indexParams.get("tbName").toString();
        rowIndexTbName = INDEX_NAME + rowIndexTbName;
        List<String> rowKeys = queryLogInfoIndexRowKeysCommon(rowIndexTbName, type, startTime, endTime, indexParams, pageSize, isNotExport);
        List<List<String>> ret = HBasePool.getInstance().
                findDataFromDbByRowKeys(tbName, rowKeys, columnArr);
        return ret;
    }

    /**
     * 查询探针索引表中主表的RowKey的值
     *
     * @param type                资源类型
     * @param startTime           起始时间
     * @param endTime             结束时间
     * @param fuzzyIndexParams    模糊匹配的参数
     * @param accurateIndexParams 精确匹配的参数
     * @param pageSize            查询的条数
     * @return
     */
    private List<String> queryProbeIndexRowKeysByThread(String type, Date startTime, Date endTime, List<LogTbKvVo> fuzzyIndexParams, List<LogTbKvVo> accurateIndexParams, Integer pageSize) {
        String timeStr = DateUtils.format(startTime, DateUtils.DATE_FORMAT_10);
        String tbName = getProbeIndexTbName(timeStr, type);

        long startTimeL = startTime.getTime();
        long endTimeL = endTime.getTime();
        long max = Long.MAX_VALUE - startTimeL;//起始
        long min = Long.MAX_VALUE - endTimeL;//结束时间;
        String starKey = String.valueOf(min);
        String endKey = String.valueOf(max);
        //一次性查询rowKey的最大长度
        final int maxRowKeySize = 1000;
        int loopSize = fuzzyIndexParams.size() % maxRowKeySize == 0 ? fuzzyIndexParams.size()
                / maxRowKeySize : fuzzyIndexParams.size() / maxRowKeySize + 1;
        List<Future<List<String>>> futureList = Lists.newArrayList();
        //循环加载数据
        for (int loop = 0; loop < loopSize; loop++) {
            int end = (loop + 1) * maxRowKeySize > fuzzyIndexParams.size() ? fuzzyIndexParams
                    .size() : (loop + 1) * maxRowKeySize;
            List<LogTbKvVo> partRowKeys = fuzzyIndexParams.subList(loop * maxRowKeySize,
                    end);
            FilterList filterList = new FilterList();
            Filter fuzzyFilter = getProbeFilterPair(partRowKeys, accurateIndexParams);
            filterList.addFilter(fuzzyFilter);
            ProbFuzzyFilterQuery hbaseDataGetter = new ProbFuzzyFilterQuery(starKey, endKey, tbName, filterList, pageSize);
            Future<List<String>> result = FIXED_ALL_LENGTH_POOL.submit(hbaseDataGetter);
            futureList.add(result);
        }
        List<String> dataQueue = Lists.newArrayList();
        try {
            for (Future<List<String>> futureSingle : futureList) {
                List<String> rdArr = futureSingle.get();
                dataQueue.addAll(rdArr);
            }
        } catch (Exception ex) {
            LOG.error("加载线程池满：" + ex.getMessage());
        }
        return dataQueue;
    }

    /**
     * 查询探针索引表中主表的RowKey的值
     *
     * @param type                资源类型
     * @param startTime           起始时间
     * @param endTime             结束时间
     * @param fuzzyIndexParams    模糊匹配的参数
     * @param accurateIndexParams 精确匹配的参数
     * @param pageSize            查询的条数
     * @return
     */
    private List<String> queryProbeIndexRowKeys(String type, Date startTime, Date endTime, List<LogTbKvVo> fuzzyIndexParams, List<LogTbKvVo> accurateIndexParams, Integer pageSize) {
        return this.queryProbeIndexRowKeys(type, startTime, endTime, fuzzyIndexParams, accurateIndexParams, pageSize, true);
    }

    /**
     * 查询探针索引表中主表的RowKey的值
     *
     * @param type                资源类型
     * @param startTime           起始时间
     * @param endTime             结束时间
     * @param fuzzyIndexParams    模糊匹配的参数
     * @param accurateIndexParams 精确匹配的参数
     * @param pageSize            查询的条数
     * @return
     */
    private List<String> queryProbeIndexRowKeys(String type, Date startTime, Date endTime, List<LogTbKvVo> fuzzyIndexParams, List<LogTbKvVo> accurateIndexParams, Integer pageSize, boolean isNotExport) {
        String timeStr = DateUtils.format(startTime, DateUtils.DATE_FORMAT_10);
        String tbName = getProbeIndexTbName(timeStr, type);

        long startTimeL = startTime.getTime();
        long endTimeL = endTime.getTime();
        long max = Long.MAX_VALUE - startTimeL;//起始
        long min = Long.MAX_VALUE - endTimeL;//结束时间
        String starKey = String.valueOf(min);
        String endKey = String.valueOf(max);
        HBasePageModel ret = new HBasePageModel(pageSize);
        FilterList filterList = new FilterList();
        if (fuzzyIndexParams.size() > 10000) {
            fuzzyIndexParams = fuzzyIndexParams.subList(0,
                    10000);
        }
        Filter fuzzyFilter = getProbeFilterPair(fuzzyIndexParams, accurateIndexParams);
        filterList.addFilter(fuzzyFilter);
        ret = HBasePool.getInstance().
                scanResultByPageFilter(tbName, null, starKey.getBytes(), endKey.
                        getBytes(), filterList, 0, ret);
        List<Result> indexResultList = ret.getResultList();
        List<String> keyRet = Lists.newArrayList();
        for (int i = 0; i < indexResultList.size(); i++) {
            Result result = indexResultList.get(i);
            for (Cell cell : result.listCells()) {
                String key = Bytes.toString(CellUtil.cloneQualifier(cell));
                if (key.equalsIgnoreCase("ROWKEY")) {
                    String value = Bytes.toString(CellUtil.cloneValue(cell));
                    keyRet.add(value);
                }
            }
        }
        List<String> newKeyRet = keyRet.stream().distinct().collect(Collectors.toList());
        newKeyRet.sort((v1, v2) -> v2.substring(3, v2.length()).compareTo(v1.substring(3, v1.length())));
        if (isNotExport) {
            if (newKeyRet.size() > 1000) {
                newKeyRet = newKeyRet.subList(0, 1000);
            }
        } else {
            if (newKeyRet.size() > 5000) {
                newKeyRet = newKeyRet.subList(0, 5000);
            }
        }
        return newKeyRet;
    }

    /**
     * 查询索引表中主表的RowKey值的公共方法
     *
     * @param tbName      数据表名
     * @param type        数据库类型
     * @param startTime   起始时间
     * @param endTime     结束时间
     * @param indexParams 索引参数  keyword：参数值 rowKeyLength：索引表rowKey的长度
     *                    tbName：索引表的名称 rowKeyName：索引字段的名称
     * @return
     */
    private List<String> queryLogInfoIndexRowKeysCommon(String tbName, String type, Date startTime, Date endTime, Map<String, Object> indexParams, Integer pageSize, boolean isNotExport) {
        long startTimeL = startTime.getTime();
        long endTimeL = endTime.getTime();

        long max = Long.MAX_VALUE - startTimeL;//起始
        long min = Long.MAX_VALUE - endTimeL;//结束时间
        String indexFlag = indexParams.get("keyword").toString();
        String endKey = "";
        String startKey = "";
        //如果有类型就需要拼接类型
        if (StringUtils.isNotBlank(type)) {
            endKey = type + max;
            startKey = type + min;
        } else {
            endKey = String.valueOf(max);
            startKey = String.valueOf(min);
        }
        if (pageSize == null) {
            pageSize = MAX_QUERY_LENGTH;
        }
        Filter rowFilter = new RowFilter(CompareFilter.CompareOp.EQUAL,
                new SubstringComparator(indexFlag));
        FilterList filterList = new FilterList();
        filterList.addFilter(rowFilter);
        HBasePageModel ret = new HBasePageModel(pageSize);
        ret = HBasePool.getInstance().
                scanResultByPageFilter(tbName, null, startKey.getBytes(), endKey.
                        getBytes(), filterList, 0, ret);
        List<Result> indexResultList = ret.getResultList();
        List<String> keyRet = Lists.newArrayList();
        for (int i = 0; i < indexResultList.size(); i++) {
            Result result = indexResultList.get(i);
            for (Cell cell : result.listCells()) {
                String key = Bytes.toString(CellUtil.cloneQualifier(cell));
                if (key.equalsIgnoreCase(indexParams.get("rowKeyName").toString())) {
                    String value = Bytes.toString(CellUtil.cloneValue(cell));
                    keyRet.add(value);
                }
            }
        }
        List<String> newKeyRet = keyRet.stream().distinct().collect(Collectors.toList());
        return newKeyRet;
    }

    private List<List<String>> queryProbeInfoNoOtherConditionFMainTb(String type, List<String> columnArr, Date startTime, Date endTime, Integer pageSize) throws ExecutionException, InterruptedException {

        String timeStr = DateUtils.format(startTime, DateUtils.DATE_FORMAT_10);
        String tbMainName = getProbeTbName(timeStr, type);
        long startTimeL = startTime.getTime();
        long endTimeL = endTime.getTime();
        long max = Long.MAX_VALUE - startTimeL;//起始
        long min = Long.MAX_VALUE - endTimeL;//结束时间
        LOG.error("========query_startTimeL==" + startTimeL);
        LOG.error("========query_endTimeL==" + endTimeL);
        LOG.info("========query_Min==" + min);
        LOG.info("========query_Max==" + max);
        String starKey = "000" + String.valueOf(min);
        String endKey = "001" + String.valueOf(max);
        HBasePageModel ret = new HBasePageModel(1000);
        ret = HBasePool.getInstance().
                scanResultByPageFilter(tbMainName, columnArr, starKey.getBytes(), endKey.
                        getBytes(), null, 0, ret);
        List<List<String>> mainRet = ret.getDataList();
        return mainRet;
    }

    /**
     * 查询探针数据没有其他条件的数据集
     *
     * @param type      类型代码
     * @param startTime 起始时间
     * @param endTime   结束时间
     * @return
     */
    private List<List<String>> queryProbeInfoNoOtherCondition(String type, List<String> columnArr, Date startTime, Date endTime, Integer pageSize) throws ExecutionException, InterruptedException {


        String timeStr = DateUtils.format(startTime, DateUtils.DATE_FORMAT_10);
        String tbName = getProbeClientIndexTbName(timeStr, type);

        long startTimeL = startTime.getTime();
        long endTimeL = endTime.getTime();
        long max = Long.MAX_VALUE - startTimeL;//起始
        long min = Long.MAX_VALUE - endTimeL;//结束时间
        String starKey = String.valueOf(min);
        String endKey = String.valueOf(max);
        int mxPageSize=1000;
        if(isExport){
            mxPageSize=5000;
        }
        HBasePageModel ret = new HBasePageModel(mxPageSize);
        ret = HBasePool.getInstance().
                scanResultByPageFilter(tbName, null, starKey.getBytes(), endKey.
                        getBytes(), null, 0, ret);
        List<Result> indexResultList = ret.getResultList();
        List<String> keyRet = Lists.newArrayList();
        for (int i = 0; i < indexResultList.size(); i++) {
            Result result = indexResultList.get(i);
            for (Cell cell : result.listCells()) {
                String key = Bytes.toString(CellUtil.cloneQualifier(cell));
                if (key.equalsIgnoreCase("ROWKEY")) {
                    String value = Bytes.toString(CellUtil.cloneValue(cell));
                    keyRet.add(value);
                }
            }
        }
        String tbMainName = getProbeTbName(timeStr, type);
        List<List<String>> mainRet = HBasePool.getInstance().
                findDataFromDbByRowKeys(tbMainName, keyRet, columnArr);

        return mainRet;
    }

    /**
     * 获取统计日志的无其他查询条件的公共方法
     *
     * @param tbName    表名
     * @param type      类型代码
     * @param columnArr 字段数组
     * @param startTime 起始时间
     * @param endTime   结束时间
     * @param pageSize  分页条数
     * @return
     */
    private HBasePageModel queryLogInfoNoOtherCondition(String tbName, String type, List<String> columnArr, Date startTime, Date endTime, Integer pageSize) {
        long startTimeL = startTime.getTime();
        long endTimeL = endTime.getTime();
        long max = Long.MAX_VALUE - startTimeL;//起始
        long min = Long.MAX_VALUE - endTimeL;//结束时间
        LOG.error("========query_startTimeL==" + startTimeL);
        LOG.error("========query_endTimeL==" + endTimeL);
        LOG.info("========query_Min==" + min);
        LOG.info("========query_Max==" + max);
        String endKey = String.valueOf(max);
        String startKey = String.valueOf(min);
        if (StringUtils.isNotBlank(type)) {
            endKey = type + endKey;
            startKey = type + startKey;
        }
        if (pageSize == null) {
            pageSize = MAX_QUERY_LENGTH;
        }
        HBasePageModel ret = new HBasePageModel(pageSize);
        ret = HBasePool.getInstance().
                scanResultByPageFilter(tbName, columnArr, startKey.getBytes(), endKey.
                        getBytes(), null, 0, ret);
        return ret;
    }

    /**
     * 探针日志主表名称
     *
     * @param timeStr 月份字符串 格式如：201702
     * @param type    类型
     * @return
     */
    private String getProbeTbName(String timeStr, String type) {
        String tbName = INDEX_NAME + "SDATA_AUDIT_DB_LOG_" + type + "_" + timeStr;
        return tbName;
    }


    /**
     * 获取探针客户端IP索引表
     *
     * @param timeStr 时间字符串
     * @param type    类型
     * @return
     */
    private String getProbeClientIndexTbName(String timeStr, String type) {
        String tbName = INDEX_NAME + "SDATA_AUDIT_DB_LOG_" + type + "_" + timeStr + "_CLIENT_IP";
        return tbName;
    }

    /**
     * 探针日志索引表
     *
     * @param timeStr 月份字符串 格式如：201702
     * @return
     */
    private String getProbeIndexTbName(String timeStr, String type) {
        String tbName = INDEX_NAME + "SDATA_AUDIT_DB_LOG_" + type + "_" + timeStr + "_INDEX";
        return tbName;
    }

    /**
     * 获取探针模糊匹配的过滤
     *
     * @param fuzzyIndexParams    索引数组 CLIENT_IP(对应的Id值)+集群类型+集群ID+数据库账户+数据库名称+表名称
     * @param accurateIndexParams 索引数组
     * @return
     */
    private Filter getProbeFilterPair(List<LogTbKvVo> fuzzyIndexParams, List<LogTbKvVo> accurateIndexParams) {
        List<Pair<byte[], byte[]>> fuzzyKeysData = Lists.newArrayList();
        fuzzyIndexParams.forEach(p -> {
            Pair<byte[], byte[]> keyPair = assembleProbePair(p, accurateIndexParams);
            fuzzyKeysData.add(keyPair);
        });
        Filter rowFilter = new FuzzyRowFilter(fuzzyKeysData);
        return rowFilter;

    }


    /**
     * 获取匹配的字段
     *
     * @param strId               字段ID
     * @param accurateIndexParams 索引参数
     * @return
     */
    private LogTbKvVo acquireIndexPair(ProbeLogIndex strId, List<LogTbKvVo> accurateIndexParams) {
        List<LogTbKvVo> currentList = accurateIndexParams.stream().filter(p -> strId.toString().equalsIgnoreCase(p.getKey())).collect(Collectors.toList());
        String key = "";
        String val = "";
        int len = strId.getLen();
        if (currentList != null && currentList.size() > 0) {
            key = currentList.get(0).getValue();
            StringBuffer valByteBuffer = new StringBuffer();
            for (int i = 0; i < len; i++) {
                if (i != 0) {
                    valByteBuffer.append(",");
                }
                valByteBuffer.append("0");
            }
            val = valByteBuffer.toString();
        } else {
            StringBuffer paramByteBuffer = new StringBuffer();
            StringBuffer valByteBuffer = new StringBuffer();
            for (int i = 0; i < len; i++) {
                paramByteBuffer.append("\\x00");
                if (i != 0) {
                    valByteBuffer.append(",");
                }
                valByteBuffer.append("1");
            }
            key = paramByteBuffer.toString();
            val = valByteBuffer.toString();
        }
        LogTbKvVo ret = new LogTbKvVo();
        ret.setKey(key);
        ret.setValue(val);
        return ret;

    }

    /**
     * 组装探针日志模糊匹配的索引
     *
     * @param fuzzyIndexParam     模糊匹配参数
     * @param accurateIndexParams 精确查询的参数字段
     * @return
     */
    private Pair<byte[], byte[]> assembleProbePair(LogTbKvVo fuzzyIndexParam, List<LogTbKvVo> accurateIndexParams) {
        StringBuffer paramByteBuffer = new StringBuffer();
        StringBuffer valByteBuffer = new StringBuffer();
        //开始模糊匹配时间字段
        for (int i = 0; i < 19; i++) {
            paramByteBuffer.append("\\x00");
            if (i != 0) {
                valByteBuffer.append(",");
            }
            valByteBuffer.append("1");
        }
        //开始模糊匹配资源字段
        LogTbKvVo resVo = acquireIndexPair(ProbeLogIndex.RESRC_ID, accurateIndexParams);
        paramByteBuffer.append(resVo.getKey());
        valByteBuffer.append(",").append(resVo.getValue());
        //开始匹配模糊查询的值
        paramByteBuffer.append(fuzzyIndexParam.getKey());
        valByteBuffer.append(",").append(fuzzyIndexParam.getValue());
        //开始匹配风险等级字段
        LogTbKvVo levelVo = acquireIndexPair(ProbeLogIndex.LEVEL, accurateIndexParams);
        paramByteBuffer.append(levelVo.getKey());
        valByteBuffer.append(",").append(levelVo.getValue());
        //开始匹配操作类型
        LogTbKvVo opertTypeVo = acquireIndexPair(ProbeLogIndex.OPER_TYPE, accurateIndexParams);
        paramByteBuffer.append(opertTypeVo.getKey());
        valByteBuffer.append(",").append(opertTypeVo.getValue());
        //开始匹配操作结果
        LogTbKvVo resultVo = acquireIndexPair(ProbeLogIndex.ACT_RESULT, accurateIndexParams);
        paramByteBuffer.append(resultVo.getKey());
        valByteBuffer.append(",").append(resultVo.getValue());
        //开始加载模糊匹配的数据
        paramByteBuffer.append("\\x00");
        valByteBuffer.append(",").append("1");
        String fPStr = paramByteBuffer.toString();
        byte[] paramByteArr = Bytes.toBytesBinary(fPStr);
        String[] valArr = valByteBuffer.toString().split(",");
        byte[] valByteArr = new byte[valArr.length];
        for (int i = 0; i < valArr.length; i++) {
            if ("1".equals(valArr[i])) {
                valByteArr[i] = 1;
            } else {
                valByteArr[i] = 0;
            }
        }
        Pair<byte[], byte[]> keyPair = Pair.newPair(paramByteArr, valByteArr);
        return keyPair;
    }

}
